package affcom;

import java.util.Vector;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JComponent;

public class Ledit extends Component
{
    private Color bgColor = Color.lightGray;
    private Color selColor = Color.white;
    private int largeurCar;
    private int hauteurCar;
    private int descentCar;

    private char[] regStr  = new char[32];
    private int nbreCar = 4;
    private int reg;
    private int posCour = 0;
    private boolean cHex = false;
    boolean inhibe = false;
    boolean focused;
    boolean isEditable = true;


    public Ledit()
    {
	try
	{
	    jbInit();
	}
	catch(Exception e)
	{
	    e.printStackTrace();
	}

    }

    private void jbInit() throws Exception
    {

	this.setFont(new java.awt.Font("Monospaced", 0, 18));

	this.addMouseListener(new java.awt.event.MouseAdapter() {
	    public void mousePressed(MouseEvent e) {
		this_mousePressed(e);
	    }
	});
	this.addKeyListener(new java.awt.event.KeyAdapter() {
	    public void keyTyped(KeyEvent e) {
		if ((!inhibe) & isEditable) this_keyTyped(e);
	    }
	    public void keyPressed(KeyEvent e) {
		if ((!inhibe) & isEditable) this_keyPressed(e);
	    }
	});
	this.addFocusListener(new java.awt.event.FocusAdapter() {
	    public void focusLost(FocusEvent e) {
		if ((!inhibe) & isEditable) this_focusLost(e);
	    }
	    public void focusGained(FocusEvent e) {
		if ((!inhibe) & isEditable) this_focusGained(e);
	    }
	});
	myDimensions();
	reTaille();
	setVal(0);
    }

    public void setEditable(boolean on)
    {
	isEditable = on;
	repaint();
    }
    public boolean isEditable()
    {
	return isEditable;
    }

    public void setBgColor(Color color)
    {
	bgColor = color;
	repaint();
    }
    public Color getBgColor()
    {
	return bgColor;
    }

    public void setFocusColor(Color selColor)
    {
	this.selColor = selColor;
	repaint();
    }
    public Color getFocusColor()
    {
	return selColor;
    }


    public void reTaille()
    {
	int longueur = (nbreCar * largeurCar);
	int hauteur = hauteurCar;
	this.setSize(new Dimension(longueur, hauteur));
    }

    public void setNbreCar(int nc)
    {
	if (nc > 32) nbreCar = 32;
	else nbreCar = nc;
	reTaille();
	setVal(reg);   //recalcul et rafraichissement
    }

    public int getNbreCar()
    {
	return nbreCar;
    }

    public void setCHex(boolean cHex)
    {
	this.cHex = cHex;
	posCour = 0;
	setVal(reg);   //recalcul et rafraichissement
    }
    public boolean isCHex()
    {
	return cHex;
    }

    public void setInhibe(boolean vb)
    {
	inhibe = vb;
	repaint();
    }
    public boolean isInhibe()
    {
	return inhibe;
    }

    public int getVal()
    {
	return reg;
    }

    public void setVal(int aVal)
    {
	reg = aVal;
	if (cHex)
	    ConvUtil.intToHexString(reg, regStr, nbreCar);
	else ConvUtil.intToBinString(reg, regStr, nbreCar);
	repaint();
    }


    //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    //                               AFFICHAGE
    //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    private void myDimensions()
    {
	java.awt.FontMetrics l = this.getFontMetrics(this.getFont());
	largeurCar = l.charWidth('0');
	hauteurCar = l.getAscent() -1;
	descentCar = l.getAscent() - (l.getDescent()/2) -2;
    }

    public void paint(Graphics g)
    {
	bgColor = getParent().getBackground();
	affiche(g);
    }

    public void affiche(Graphics g)
    {
	myDimensions();
	for (int x = 0; x < nbreCar; x++)
	{
	    afficheCaractere(g, x);
	}
    }

    public void afficheCaractere(Graphics og, int x)
    {
	if (inhibe)
	{
	    char[] croix = "X".toCharArray();
	    og.setColor(Color.lightGray);
	    og.fillRect((x * largeurCar), 0, largeurCar, 16);
	    og.setColor(Color.gray);
	    og.drawChars(croix, 0, 1, (x * largeurCar), 14);
	}
	else
	{
	    if (focused)
	    {
		if (posCour == x )
		{
		    og.setColor(Color.black);
		    og.fillRect((x * largeurCar), 0, largeurCar, 16);
		    og.setColor(Color.white);
		}
		else
		{
		    og.setColor(selColor);
		    og.fillRect((x * largeurCar), 0, largeurCar, 16);
		    og.setColor(Color.black);
		}
	    }
	    else
	    {
		og.setColor(bgColor);
		og.fillRect((x * largeurCar), 0, largeurCar, 16);
		og.setColor(Color.black);
	    }
	    og.drawChars(regStr, x, 1, (x * largeurCar), 14);
	}
    }

    private void incPosCour()
    {
	if (posCour == nbreCar-1)
	{
	    posCour = 0;
	}
	else posCour++;

    }

    private void decPosCour()
    {
	if (posCour == 0)
	{
	    posCour = nbreCar-1;
	}
	else posCour--;

    }



    /**
     * ****************************************************************************
     */

    void this_keyPressed(KeyEvent e)
    {

	switch (e.getKeyCode())
	{
	    case KeyEvent.VK_LEFT:
	    {
		decPosCour();
		repaint();
		break;
	    }
	case KeyEvent.VK_RIGHT:
	{
	    incPosCour();
	    repaint();
	    break;
	}
    case KeyEvent.VK_UP:
    {
	if (cHex)
	{
	    regStr[posCour] = ConvUtil.hexPred(regStr[posCour]);
	    reg = ConvUtil.strHexToInt(regStr, nbreCar);
	}
	else
	{
	    regStr[posCour] = ConvUtil.binCompl(regStr[posCour]);
	    reg = ConvUtil.strBinToInt(regStr, nbreCar);
	}
	repaint();
	change(reg);
	break;
    }
case KeyEvent.VK_DOWN:
{
    if (cHex)
    {
	regStr[posCour] = ConvUtil.hexSucc(regStr[posCour]);
	reg = ConvUtil.strHexToInt(regStr, nbreCar);

    }
    else
    {
	regStr[posCour] = ConvUtil.binCompl(regStr[posCour]);
	reg = ConvUtil.strBinToInt(regStr, nbreCar);
    }
    //affiche();
    repaint();
    change(reg);
    break;
}
case KeyEvent.VK_END:
{
    posCour = nbreCar-1;
    repaint();
    break;
}
case KeyEvent.VK_HOME:
{
    posCour = 0;
    repaint();
    break;
}
	}
    }

    void this_keyTyped(KeyEvent e)
    {
	char caractere = e.getKeyChar();

	if (cHex)
	{
	    if (ConvUtil.caractereHexValide(caractere))
	    {
		regStr[posCour] = Character.toLowerCase(caractere);
		incPosCour();
		repaint();
		reg = ConvUtil.strHexToInt(regStr, nbreCar);
		change(reg);
	    }
	}
	else
	{
	    if (ConvUtil.caractereBinValide(caractere))
	    {
		regStr[posCour] = caractere;
		incPosCour();
		repaint();
		reg = ConvUtil.strBinToInt(regStr, nbreCar);
		change(reg);
	    }
	}
    }



    void this_focusGained(FocusEvent e)
    {
	focused = true;
	repaint();
    }

    void this_focusLost(FocusEvent e)
    {
	focused = false;
	repaint();
    }

    void this_mousePressed(MouseEvent e)
    {
	this.requestFocus();
	if ((e.getModifiers() & MouseEvent.BUTTON1_MASK ) == MouseEvent.BUTTON1_MASK)
	{
	    posCour = e.getX() / largeurCar;
	    repaint();
	}

    }


//******************************************************************************

    public void change(int val)
    {
	if (!inhibe)
	{
	    if (getParent() instanceof EditeurRegistre)
	     ((EditeurRegistre)getParent()).change(val);
	}
    }


}